package com.yunc.modules.oa.controller;

import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrSpliter;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yunc.base.controller.CommonController;
import com.yunc.common.utils.R;
import com.yunc.modules.oa.entity.dto.ActivitiDTO;
import com.yunc.modules.oa.entity.dto.UserDTO;
import com.yunc.modules.oa.entity.vo.ActivitiNodeVO;
import com.yunc.modules.oa.entity.vo.HistoricTaskVO;
import com.yunc.modules.oa.service.IActivitiService;
import com.yunc.modules.sys.entity.SysUser;
import com.yunc.modules.sys.service.ISysUserService;
import org.activiti.bpmn.model.*;
import org.activiti.engine.*;
import org.activiti.engine.history.HistoricTaskInstance;
import org.activiti.engine.identity.Group;
import org.activiti.engine.identity.User;
import org.activiti.engine.runtime.Execution;
import org.activiti.engine.task.Task;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.*;

/**
 * 工作流相关分页页面
 *
 * @author congcong tao
 * @date 2019/2/19 14:23
 */
@RestController
@RequestMapping("/activiti")
public class ActivitiController extends CommonController {

    private static final Logger logger = LogManager.getLogger(ActivitiController.class);

    @Autowired
    private IActivitiService activitiService;
    @Autowired
    private TaskService taskService;
    @Autowired
    private RepositoryService repositoryService;
    @Autowired
    private RuntimeService runtimeService;
    @Autowired
    private HistoryService historyService;
    @Autowired
    private IdentityService identityService;
    @Autowired
    private ISysUserService sysUserService;

    /**
     * 我发起的
     */
    @GetMapping(value="/taskStartPage")
    public R taskStartPage(Page<ActivitiDTO> page, ActivitiDTO activitiDTO){
        activitiDTO.setProposer(getUserIdStr());
        activitiService.taskStartPage(page, activitiDTO);
        return R.ok().put("data", page.getRecords()).put("count", page.getTotal());
    }

    /**
     * 我的待办
     */
    @GetMapping(value="/taskCheckingPage")
    public R taskCheckingPage(Page<ActivitiDTO> page, ActivitiDTO activitiDTO){
        activitiDTO.setProposer(getUserIdStr());
        activitiService.taskCheckingPage(page, activitiDTO);
        return R.ok().put("data", page.getRecords()).put("count", page.getTotal());
    }

    /**
     * 我的已办
     */
    @GetMapping(value="/taskCheckedPage")
    public R taskCheckedPage(Page<ActivitiDTO> page, ActivitiDTO activitiDTO){
        activitiDTO.setProposer(getUserIdStr());
        activitiService.taskCheckedPage(page, activitiDTO);
        return R.ok().put("data", page.getRecords()).put("count", page.getTotal());
    }

    /**
     * 查询历史活动
     */
    @GetMapping(value="/selectHisActivitiList")
    public R selectHisActivitiList(ActivitiDTO activitiDTO){
        List<HistoricTaskInstance> list = historyService
                .createHistoricTaskInstanceQuery()
                .processInstanceId(activitiDTO.getProcessInstanceId())
                .list();
        List<HistoricTaskVO> taskList = new ArrayList<>();
        if (list != null && list.size() > 0) {
            for (HistoricTaskInstance hti : list) {
                HistoricTaskVO historicTask = new HistoricTaskVO();
                SysUser sysUser = sysUserService.getById(hti.getAssignee());
                if (sysUser != null) {
                    historicTask.setAssignee(sysUser.getUserName());
                } else {
                    historicTask.setAssignee(hti.getAssignee());
                }
                historicTask.setName(hti.getName());
                // 计算时间差
                String startTime = "";
                long minute = DateUtil.between(hti.getStartTime(), DateUtil.date(), DateUnit.MINUTE);
                if (minute >= 60) {
                    long hour = DateUtil.between(hti.getStartTime(), DateUtil.date(), DateUnit.HOUR);
                    if (hour >= 24) {
                        long day = DateUtil.between(hti.getStartTime(), DateUtil.date(), DateUnit.DAY);
                        startTime = day + "天前";
                    } else {
                        startTime = hour + "小时前";
                    }
                } else if (minute == 0){
                    startTime = "刚刚";
                } else {
                    startTime = minute + "分钟前";
                }
                historicTask.setStartTime(startTime);
                // historicTask.setEndTime(DateUtil.formatDateTime(hti.getEndTime()));
                taskList.add(historicTask);
            }
        }
        return R.ok().put("list", taskList);
    }

    /**
     * 获取第一个流程节点
     */
    @GetMapping(value="/getFirstTaskNodeList")
    public R getFirstTaskNodeList(String params){
        JSONObject parseObject = (JSONObject) JSON.parse(params);
        String processId = (String) parseObject.get("processId");
        Map<String, Object> paramsObjectMap = (Map<String, Object>) parseObject.get("params");
        Map<String, Object> paramsMap = new HashMap<>(0);
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processId);
        // 查询所有流程节点（流元素）
        Collection<FlowElement> flowElements = bpmnModel.getMainProcess().getFlowElements();
        List<SequenceFlow> outgoingFlows = new ArrayList<>();
        for (FlowElement flowElement : flowElements) {
            // 查询开始节点
            if (flowElement instanceof StartEvent) {
                StartEvent startEvent = (StartEvent) flowElement;
                if (startEvent != null) {
                    outgoingFlows = startEvent.getOutgoingFlows();
                    break;
                }
            }
        }
        List<ActivitiNodeVO> userTaskList = new ArrayList<>();
        List<ActivitiNodeVO> maps = activitiService.iteratorNextNodes(paramsMap, outgoingFlows, userTaskList);
        // 只获取一个
        if (maps != null && maps.size() > 0) {
            ActivitiNodeVO userTaskMap = maps.get(0);
            if (userTaskMap != null) {
                String id = userTaskMap.getId();
                FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(id);
                userTaskList = new ArrayList<>();
                maps = activitiService.iteratorNextNodes(paramsObjectMap, flowNode.getOutgoingFlows(), userTaskList);
            }
        }
        return R.ok().put("activitiNodeList", maps);
    }

    /**
     * 查询下一个环节流程节点
     */
    @GetMapping(value="/getNextTaskNodeList")
    public R getNextTaskNodeList(String params){
        JSONObject parseObject = (JSONObject) JSON.parse(params);
        String processId = (String) parseObject.get("processId");
        String taskId = (String) parseObject.get("taskId");
        Map<String, Object> paramsObjectMap = (Map<String, Object>) parseObject.get("params");
        BpmnModel bpmnModel = repositoryService.getBpmnModel(processId);
        Task task = taskService.createTaskQuery()
                .taskId(taskId)
                .singleResult();
        Execution execution = runtimeService.createExecutionQuery().executionId(task.getExecutionId()).singleResult();
        String activityId = execution.getActivityId();
        FlowNode flowNode = (FlowNode) bpmnModel.getMainProcess().getFlowElement(activityId);
        List<SequenceFlow> outgoingFlows = flowNode.getOutgoingFlows();
        // 需要递归查询，直至查询到userTask
        List<ActivitiNodeVO> userTaskList = new ArrayList<>();
        List<ActivitiNodeVO> maps = activitiService.iteratorNextNodes(paramsObjectMap, outgoingFlows, userTaskList);
        Long staffId = (Long) taskService.getVariable(task.getId(), "staff");
        SysUser sysUser = null;
        if (staffId != null) {
            sysUser = sysUserService.getById(staffId);
        }
        return R.ok().put("activitiNodeList", maps).put("sysUser", sysUser);
    }

    /**
     * 获取流程图及当前位置
     */
    @GetMapping(value = "/image")
    public void image(HttpServletResponse response, String processInstanceId) {
        try {
            InputStream is = activitiService.getDiagram(processInstanceId);
            if (is == null) {
                return;
            }
            response.setContentType("image/png");
            BufferedImage image = ImageIO.read(is);
            OutputStream out = response.getOutputStream();
            ImageIO.write(image, "png", out);
            is.close();
            out.close();
        } catch (Exception ex) {
            logger.error("查看流程图失败", ex);
        }
    }

    /**
     * 流程审核
     * 处理会签，或签
     */
    @PutMapping(value = "/complete")
    public R update(String taskId, String result, String assignee){
        Map<String, Object> variable = new HashMap<>(2);
        if (StringUtils.isNotEmpty(result)) {
            variable.put("result", result);
        }
        if (StringUtils.isNotEmpty(assignee)) {
            // 如何判断是这个环节是会签
            if(assignee.contains(",")){
                List<String> assigneeList = StrSpliter.split(assignee, ',', 0, true, true);
                // 如果需要是会签，且需要控制驳回（如：一人驳回所有都驳回）
                if (StringUtils.equals("0", result)) {
                    //nrOfDisPassInstances默认设置为0
                    taskService.setVariable(taskId, "nrOfDisPassInstances", 1);
                } /*else {
                    Map<String, Object> taskVariable = taskService.getVariables(taskId);
                    // 审核完成数量
                    Object object = taskVariable.get("nrOfCompletedInstances");
                    if (object != null && (Integer) object > 0) {
                        // 重新审核
                        assigneeList.addAll((List<String>) taskVariable.get("assigneeList"));
                    }
                }*/
                variable.put("assigneeList", assigneeList);
            } else {
                variable.put("assignee", assignee);
            }
        }
        taskService.complete(taskId, variable, false);
        return R.ok();
    }

    /**
     * 工作组信息
     */
    @GetMapping("/groupPage")
    public R groupPage(Page<Group> page, Group group){
        long current = page.getCurrent() - 1;
        long size = page.getSize();
        List<Group> dataList = identityService.createGroupQuery().listPage((int) current, (int) size);
        long countSize = identityService.createGroupQuery().count();
        return R.ok().put("data", dataList).put("count", countSize);
    }

    @GetMapping("/groupInfo/{id}")
    public R groupInfo(@PathVariable String id){
        Group group = identityService.createGroupQuery().groupId(id).singleResult();
        return R.ok().put("oaGroup", group);
    }

    @PostMapping("/groupSave")
    public R groupSave(String id, String name){
        Group group;
        if (StringUtils.isEmpty(id)) {
            id = IdUtil.simpleUUID();
            group = identityService.newGroup(id);
        } else {
            group = identityService.createGroupQuery().groupId(id).singleResult();
        }
        group.setName(name);
        group.setType("1");
        identityService.saveGroup(group);
        return R.ok();
    }

    @PostMapping("/userSave")
    public R userSave(String groupId, String userIds){
        if (StringUtils.isEmpty(groupId) || StringUtils.isEmpty(userIds)) {
            return R.error();
        }
        String[] userIdArr = userIds.split(",");
        if (userIdArr == null || userIdArr.length == 0) {
            return R.error();
        }
        for (String userId : userIdArr) {
            User user = identityService.createUserQuery().userId(userId).singleResult();
            if (user == null) {
                user = identityService.newUser(userId);
                SysUser sysUser = sysUserService.getById(userId);
                user.setFirstName(sysUser.getUserName());
                user.setLastName(sysUser.getLoginName());
                user.setEmail(sysUser.getMail());
                identityService.saveUser(user);
            }
            identityService.createMembership(userId, groupId);
        }
        return R.ok();
    }

    @DeleteMapping("/userDelete")
    public R userDelete(String groupId, String userIds){
        if (StringUtils.isEmpty(groupId) || StringUtils.isEmpty(userIds)) {
            return R.error();
        }
        String[] userIdArr = userIds.split(",");
        if (userIdArr == null || userIdArr.length == 0) {
            return R.error();
        }
        for (String userId : userIdArr) {
            identityService.deleteMembership(userId, groupId);
        }
        return R.ok();
    }

    @GetMapping("/groupUserPage")
    public R groupUserPage(Page<UserDTO> page, UserDTO userDTO){
        Page<UserDTO> userPage = activitiService.groupUserPage(page, userDTO);
        return R.ok().put("data", userPage.getRecords()).put("count", userPage.getTotal());
    }

    @GetMapping("/userPage")
    public R userPage(Page<UserDTO> page, UserDTO userDTO){
        Page<UserDTO> userPage = activitiService.userPage(page, userDTO);
        return R.ok().put("data", userPage.getRecords()).put("count", userPage.getTotal());
    }
}
